package wiki.kaizen.cloud.security.session.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.StringUtils;
import org.iherus.shiro.cache.redis.RedisCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import wiki.kaizen.cloud.security.session.properties.SecurityProperties;
import wiki.kaizen.cloud.security.session.support.KaizenSecurityManager;
import wiki.kaizen.cloud.security.session.support.KaizenSessionManager;
import wiki.kaizen.cloud.security.session.support.filter.KickoutControlFilter;

import javax.servlet.Filter;
import java.io.Serializable;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroFilterConfig {

    private final SecurityProperties securityProperties;

    public ShiroFilterConfig(SecurityProperties securityProperties) {
        this.securityProperties = securityProperties;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(
        KaizenSecurityManager securityManager,
        KickoutControlFilter kickoutControlFilter
    ){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        /*
         * 设置安全管理器
         * */
        bean.setSecurityManager(securityManager);
        /*
         * 设置登录地址 权限不足地址
         * */
        SecurityProperties.SecurityFilter propFilter = securityProperties.getSecurityFilter();
        bean.setLoginUrl(propFilter.getLoginUrl());
        bean.setUnauthorizedUrl(propFilter.getUnauthorizedUrl());
        Map<String, Filter> filterMap = bean.getFilters();

        filterMap.put("kickout",kickoutControlFilter);
        bean.setFilters(filterMap);
        Map<String, String> filterChainMap = new LinkedHashMap<>();
        List<String> anons = propFilter.getAnons();

        filterChainMap.put(securityProperties.getAccount().getKickoutUrl(),"anon");
        filterChainMap.put(propFilter.getLockedUrl(),"anon");

        if( anons!=null &&anons.size()>0 ){
            anons.forEach(
                anon-> {
                    if (StringUtils.hasLength(anon)){
                        filterChainMap.put(anon,"anon");
                    }
                }
            );
        }

        List<String> authcs = propFilter.getAuthcs();
        if( authcs!=null &&authcs.size()>0 ){
            authcs.forEach(
                authc-> {
                    if (StringUtils.hasLength(authc)){
                        filterChainMap.put(authc,"authc");
                    }
                }
            );
        }

        filterChainMap.put("/**","kickout,user");
        bean.setFilterChainDefinitionMap(filterChainMap);

        return bean;
    }

    @SuppressWarnings("unchecked")
    @Bean
    public KickoutControlFilter kickoutControlFilter(
        KaizenSessionManager sessionManager,
        RedisCache<String, Deque<Serializable>> kickout
    ){
        KickoutControlFilter iAccessControlFilter = new KickoutControlFilter();
        iAccessControlFilter.setAccessAccount(securityProperties.getAccount());
        iAccessControlFilter.setSessionManager(sessionManager);
        iAccessControlFilter.setCache(kickout);
        return iAccessControlFilter;

    }

}
